
#include "devinsight.h"




DVI_DEF_GDB_FUNCTION(dviBuffer, "解析打印buffer相关内容，状态位、引用计数等。")
const char* dviBuffer(Buffer buffer)
{
    StringInfoData res;
    initStringInfo(&res);
    BufferDesc* desc = BufferGetBufferDescriptor(buffer);


    uint64 buf_state = LockBufHdr(desc);

    appendStringInfo(&res, "Buffer: %d\n", buffer);
    appendStringInfo(&res, "Buffer Tag: %u/%u/%u/%d/%u %d-%u\n",
        desc->tag.rnode.spcNode, desc->tag.rnode.dbNode, desc->tag.rnode.relNode,
        desc->tag.rnode.bucketNode, desc->tag.rnode.opt,
        desc->tag.forkNum, desc->tag.blockNum);

    appendStringInfo(&res, "State: %lu [%s]\n", desc->state, bx64b((void*)&desc->state));
    appendStringInfo(&res, "\t64b-BM_PERMANENT: %s\n", desc->state & BM_PERMANENT ? "true" : "false");
    appendStringInfo(&res, "\t63b-BM_CHECKPOINT_NEEDED: %s\n", desc->state & BM_CHECKPOINT_NEEDED ? "true" : "false");
    appendStringInfo(&res, "\t62b-BM_PIN_COUNT_WAITER: %s\n", desc->state & BM_PIN_COUNT_WAITER ? "true" : "false");
    appendStringInfo(&res, "\t61b-BM_JUST_DIRTIED: %s\n", desc->state & BM_JUST_DIRTIED ? "true" : "false");
    appendStringInfo(&res, "\t60b-BM_IO_ERROR: %s\n", desc->state & BM_IO_ERROR ? "true" : "false");
    appendStringInfo(&res, "\t59b-BM_IO_IN_PROGRESS: %s\n", desc->state & BM_IO_IN_PROGRESS ? "true" : "false");
    appendStringInfo(&res, "\t58b-BM_TAG_VALID: %s\n", desc->state & BM_TAG_VALID ? "true" : "false");
    appendStringInfo(&res, "\t57b-BM_VALID: %s\n", desc->state & BM_VALID ? "true" : "false");
    appendStringInfo(&res, "\t56b-BM_DIRTY: %s\n", desc->state & BM_DIRTY ? "true" : "false");
    appendStringInfo(&res, "\t55b-BM_LOCKED: %s\n", desc->state & BM_LOCKED ? "true" : "false");
    appendStringInfo(&res, "\t54b-BM_IS_TMP_BUF: %s\n", desc->state & BM_IS_TMP_BUF ? "true" : "false");
    appendStringInfo(&res, "\t53-51b-??? \n");
    appendStringInfo(&res, "\t50b-BM_IS_META: %s\n", desc->state & BM_IS_META ? "true" : "false");
    appendStringInfo(&res, "\t49b-BM_IN_MIGRATE: %s\n", desc->state & BM_IN_MIGRATE ? "true" : "false");
    appendStringInfo(&res, "\t48-0b - TODO\n");

    appendStringInfo(&res, "LWLock:\n");
    appendStringInfo(&res, "\tcontent lock: %p\n", desc->content_lock);
    appendStringInfo(&res, "\tio lock: %p\n", desc->io_in_progress_lock);

    appendStringInfo(&res, "Page: (Page)%p\n", BufferGetPage(buffer));

    UnlockBufHdr(desc, buf_state);
    return (const char*)res.data;
}


DVI_DEF_SQL_FUNCTION(dvi_buffer, "查看一个buffer当前存放的 buffer desc。")
Datum dvi_buffer(PG_FUNCTION_ARGS)
{
    int buffer = PG_GETARG_INT32(0);
    if (buffer < 1 || buffer > TOTAL_BUFFER_NUM) {
        PG_RETURN_CSTRING("buffer 范围不对。");
    }

    PG_RETURN_CSTRING(dviBuffer(buffer));
}


DVI_DEF_SQL_FUNCTION(dvi_buffer_find_page, "查看一个页面(格式1663/16767/4987/16384/0 0-1324194)在不在buffer中，并返回 buffer desc")
Datum dvi_buffer_find_page(PG_FUNCTION_ARGS)
{
    char* page = TextDatumGetCString(PG_GETARG_TEXT_P(0));

    int num1, num2, num3, num4, num5, num6, num7;
    sscanf(page, "%d/%d/%d/%d/%d %d-%d", &num1, &num2, &num3, &num4, &num5, &num6, &num7);

    BufferTag buftag;
    buftag.rnode.spcNode = num1;
    buftag.rnode.dbNode = num2;
    buftag.rnode.relNode = num3;
    buftag.rnode.bucketNode = num4;
    buftag.rnode.opt = num5;
    buftag.forkNum = num6;
    buftag.blockNum = num7;

    uint32 buftag_hash = BufTableHashCode(&buftag);
    int buf_id = BufTableLookup(&buftag, buftag_hash);
    if (buf_id < 0) {
        PG_RETURN_CSTRING("没找到。");
    }

    PG_RETURN_CSTRING(dviBuffer(buf_id + 1));
}




